package com.mashibing.webmaster.realm;

import com.mashibing.webmaster.entity.SmsUser;
import com.mashibing.webmaster.service.SmsUserService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @author SNA
 * @date 2025/10/23
 * @Description 自定义Realm
 **/
@Component
public class ShiroRealm extends AuthorizingRealm {

    @Autowired
    private SmsUserService smsUserService;

    /**
     * 这段代码是Shiro安全框架中用于配置密码加密匹配器的静态代码块，主要作用是设置Realm的凭证匹配机制。
     *
     * 该代码块在ShiroRealm类加载时自动执行
     * 配置后，Shiro在进行用户认证时会使用MD5算法对密码进行1024次迭代加密处理
     * 确保用户输入的密码与数据库中存储的加密密码能够正确匹配，提高了系统的安全性，防止密码被轻易破解
     */
    {
        // 创建一个基于哈希算法的凭证匹配器实例
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        // 指定使用MD5算法进行密码加密
        credentialsMatcher.setHashAlgorithmName("MD5");
        // 设置加密迭代次数为1024次，增强密码安全性
        credentialsMatcher.setHashIterations(1024);
        // 将配置好的凭证匹配器设置到当前ShiroRealm实例中
        this.setCredentialsMatcher(credentialsMatcher);
    }


    /**
     * 执行认证逻辑，获取用户的身份验证信息
     *
     * @param authenticationToken 包含用户登录凭证的认证令牌
     * @return AuthenticationInfo 用户的身份验证信息，如果用户不存在则返回null
     * @throws AuthenticationException 认证过程中可能抛出的异常
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //1、基于authenticationToken拿到用户名
        String username = (String) authenticationToken.getPrincipal();

        //2、基于用户名获取用户信息(模拟数据库操作)
        SmsUser smsUser = smsUserService.findByUsername(username);

        //3、查询完毕后，查看用户是否为null，为null就直接返回即可
        if (smsUser == null) {
            // 用户名错误
            return null;
        }


        //4、不为null，说明用户名正确，封装AuthenticationInfo返回即可,设置密码加密方式和信息
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(smsUser, smsUser.getPassword(), "ShiroRealm");
        // 设置密码加密盐
        info.setCredentialsSalt(ByteSource.Util.bytes(smsUser.getSalt()));

        //5、返回
        return info;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

}
